#pragma once

#include "Protocol.hpp"
#include "Socket.hpp"

#include <string>
#include <functional>
#include <pthread.h>

using func_t = std::function<std::string(std::string&,bool*)>;

class TcpServer;

class ThreadDate
{
public:
    ThreadDate(TcpServer* tser_this, Socket* socket)
        :_this(tser_this),_socket(socket)
    {}

public:
    TcpServer* _this;
    Socket* _socket;
};

class TcpServer
{
public:
    TcpServer(uint16_t port,func_t handler_request)    
        :_port(port),_listensock(new TcpSocket()),_handler_request(handler_request)
    {
        _listensock->BuildListenSocketMethod(_port);
    }

    static void* HandlerRequest(void* arg)
    {
        pthread_detach(pthread_self());
        ThreadDate* th = (ThreadDate*)arg;
        std::string inbufferstream;
        bool ok = true;
        while(1)
        {
            // 1、读取报文
            if(!th->_socket->Recv(inbufferstream,1024)) break;
            // 2、调用函数处理报文
            std::string send_string = th->_this->_handler_request(inbufferstream,&ok);
            // 3、发送
            th->_socket->Send(send_string);
        }

        th->_socket->CloseSockFd();
        delete th->_socket;
        delete th;

        return nullptr;
    }

    void Loop()
    {
        while (1)
        {
            std::string clientip;
            uint16_t clientport;
            // 接收连接会返回一个新的文件描述符
            Socket *NewSocket = _listensock->AcceptConnection(&clientip, &clientport);
            std::cout << "get a new sockfd , sockfd : " << NewSocket->GetSockFd() 
                << " , clinet info " << clientip << ":" << clientport << std::endl;

            // 创建线程
            pthread_t pid;
            ThreadDate* td = new ThreadDate(this,NewSocket);
            pthread_create(&pid,nullptr,HandlerRequest,td);
        }

        _listensock->CloseSockFd();
    }

    ~TcpServer()
    {
    }
private:
    TcpSocket* _listensock; // 监听套接字
    uint16_t _port;
public:
    func_t _handler_request; // 回调函数
};